<template>
  <div class="realtime-preview">
    <div class="preview-header">
      <div class="connection-status" :class="connectionStatus">
        {{ statusMessage }}
      </div>
    </div>
    
    <div class="preview-content">
      <canvas 
        ref="previewCanvas" 
        class="preview-canvas"
        :width="canvasWidth"
        :height="canvasHeight"
      ></canvas>
      
      <div v-if="!previewTaskId" class="preview-placeholder">
        <p>Start a preview to see the animation</p>
        <button @click="startPreview" class="start-button">Start Preview</button>
      </div>
    </div>
    
    <div class="preview-controls">
      <button @click="play" :disabled="isPlaying || !previewTaskId" class="control-button">
        <i class="play-icon"></i> Play
      </button>
      <button @click="pause" :disabled="!isPlaying || !previewTaskId" class="control-button">
        <i class="pause-icon"></i> Pause
      </button>
      <button @click="stop" :disabled="!previewTaskId" class="control-button">
        <i class="stop-icon"></i> Stop
      </button>
      
      <div class="time-display">
        {{ formatTime(currentTime) }} / {{ formatTime(totalTime) }}
      </div>
      
      <button @click="toggleFullscreen" class="control-button">
        <i class="fullscreen-icon"></i> 
        {{ isFullscreen ? 'Exit Fullscreen' : 'Fullscreen' }}
      </button>
    </div>
  </div>
</template>

<script>
import apiService from '../../services/api.js';
import websocketService from '../../services/websocket.js';

export default {
  name: 'RealtimePreview',
  props: {
    projectId: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      canvasWidth: 800,
      canvasHeight: 600,
      currentTime: 0,
      totalTime: 300, // 5 minutes default
      isPlaying: false,
      isFullscreen: false,
      previewTaskId: null,
      connectionStatus: 'disconnected', // disconnected, connecting, connected, error
      statusMessage: 'Disconnected'
    };
  },
  mounted() {
    this.setupCanvas();
    this.setupWebSocketListeners();
  },
  beforeUnmount() {
    this.closeWebSocket();
    this.cleanupWebSocketListeners();
  },
  methods: {
    setupCanvas() {
      const canvas = this.$refs.previewCanvas;
      if (canvas) {
        const ctx = canvas.getContext('2d');
        // Clear canvas
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
    },
    
    setupWebSocketListeners() {
      websocketService.on('open', this.onWebSocketOpen);
      websocketService.on('frame', this.onWebSocketFrame);
      websocketService.on('status', this.onWebSocketStatus);
      websocketService.on('error', this.onWebSocketError);
      websocketService.on('close', this.onWebSocketClose);
    },
    
    cleanupWebSocketListeners() {
      websocketService.off('open', this.onWebSocketOpen);
      websocketService.off('frame', this.onWebSocketFrame);
      websocketService.off('status', this.onWebSocketStatus);
      websocketService.off('error', this.onWebSocketError);
      websocketService.off('close', this.onWebSocketClose);
    },
    
    onWebSocketOpen(event) {
      this.connectionStatus = 'connected';
      this.statusMessage = 'Connected';
      console.log('WebSocket connection opened');
    },
    
    onWebSocketFrame(frameData) {
      // Handle frame data - could be JSON metadata or binary image data
      if (typeof frameData === 'string') {
        // JSON metadata
        try {
          const metadata = JSON.parse(frameData);
          this.currentTime = metadata.time || this.currentTime;
        } catch (e) {
          console.error('Error parsing frame metadata:', e);
        }
      } else if (frameData instanceof Blob) {
        // Binary image data
        this.renderFrame(frameData);
      }
    },
    
    onWebSocketStatus(statusData) {
      console.log('WebSocket status update:', statusData);
      if (statusData.time) {
        this.currentTime = statusData.time;
      }
    },
    
    onWebSocketError(error) {
      console.error('WebSocket error:', error);
      this.connectionStatus = 'error';
      this.statusMessage = 'Connection error';
    },
    
    onWebSocketClose(event) {
      console.log('WebSocket closed:', event);
      if (this.connectionStatus !== 'error') {
        this.connectionStatus = 'disconnected';
        this.statusMessage = 'Disconnected';
      }
    },
    
    async startPreview() {
      try {
        this.connectionStatus = 'connecting';
        this.statusMessage = 'Starting preview...';
        
        const response = await apiService.startPreview(this.projectId);
        this.previewTaskId = response.taskId;
        
        console.log(`Preview started with task ID: ${this.previewTaskId}`);
        await websocketService.connect(this.previewTaskId);
      } catch (error) {
        console.error('Failed to start preview:', error);
        this.connectionStatus = 'error';
        this.statusMessage = 'Failed to start preview';
      }
    },
    
    renderFrame(frameData) {
      // Create image from frame data and draw on canvas
      const canvas = this.$refs.previewCanvas;
      if (!canvas) return;
      
      const ctx = canvas.getContext('2d');
      const img = new Image();
      
      img.onload = () => {
        // Clear canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // Draw image, scaling to fit canvas
        const scale = Math.min(
          canvas.width / img.width,
          canvas.height / img.height
        );
        
        const width = img.width * scale;
        const height = img.height * scale;
        const x = (canvas.width - width) / 2;
        const y = (canvas.height - height) / 2;
        
        ctx.drawImage(img, x, y, width, height);
      };
      
      img.src = URL.createObjectURL(frameData);
    },
    
    closeWebSocket() {
      websocketService.disconnect();
      this.connectionStatus = 'disconnected';
      this.statusMessage = 'Disconnected';
      this.previewTaskId = null;
    },
    
    play() {
      this.isPlaying = true;
      // Send play command to backend
      websocketService.send({ command: 'play' });
      console.log('Preview playback started');
    },
    
    pause() {
      this.isPlaying = false;
      // Send pause command to backend
      websocketService.send({ command: 'pause' });
      console.log('Preview playback paused');
    },
    
    stop() {
      this.isPlaying = false;
      this.currentTime = 0;
      
      // Send stop command to backend
      websocketService.send({ command: 'stop' });
      
      // Close WebSocket and reset preview
      this.closeWebSocket();
      
      // Clear canvas
      const canvas = this.$refs.previewCanvas;
      if (canvas) {
        const ctx = canvas.getContext('2d');
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
      
      console.log('Preview stopped');
    },
    
    toggleFullscreen() {
      this.isFullscreen = !this.isFullscreen;
      // Toggle fullscreen mode
      console.log('Toggle fullscreen:', this.isFullscreen);
    },
    
    formatTime(seconds) {
      const mins = Math.floor(seconds / 60);
      const secs = Math.floor(seconds % 60);
      const millis = Math.floor((seconds % 1) * 100);
      return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}.${millis.toString().padStart(2, '0')}`;
    }
  }
};
</script>

<style scoped>
.realtime-preview {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.preview-header {
  padding: 10px 15px;
  border-bottom: 1px solid #eee;
  background-color: #f5f5f5;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.connection-status {
  font-size: 12px;
  padding: 3px 8px;
  border-radius: 10px;
  color: white;
}

.connection-status.disconnected {
  background-color: #6c757d;
}

.connection-status.connecting {
  background-color: #ffc107;
  color: #000;
}

.connection-status.connected {
  background-color: #28a745;
}

.connection-status.error {
  background-color: #dc3545;
}

.preview-content {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #000;
  overflow: hidden;
  position: relative;
}

.preview-canvas {
  max-width: 100%;
  max-height: 100%;
  background-color: #000;
}

.preview-placeholder {
  position: absolute;
  text-align: center;
  color: #fff;
}

.start-button {
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  margin-top: 10px;
}

.start-button:hover {
  background-color: #0056b3;
}

.preview-controls {
  padding: 10px 15px;
  border-top: 1px solid #eee;
  background-color: #f5f5f5;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 15px;
}

.control-button {
  padding: 8px 15px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 5px;
}

.control-button:hover {
  background-color: #0056b3;
}

.control-button:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
}

.time-display {
  font-family: monospace;
  font-size: 14px;
  min-width: 120px;
  text-align: center;
}
</style>